package net

import (
	"encoding/json"
	"errors"
	"fmt"
	gameConfig "framework/game"
	"framework/protocol"
	"framework/remote"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
	"math/rand"
	"net/http"
	"strings"
	"sync"
	"time"
)

var (
	websocketUpgrade = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	}
)

type CheckOriginHandler func(r *http.Request) bool
type EventHandler func(packet *protocol.Packet, c Connection) error
type LogicHandler map[string]HandlerFunc
type HandlerFunc func(session *Session, data []byte) (any, error)

/*
*
websocket管理器
创建ws服务
*/
type Manager struct {
	sync.RWMutex
	websocketUpgrade   *websocket.Upgrader
	ServerId           string
	CheckOriginHandler CheckOriginHandler
	clients            map[string]Connection                 //看这里，Connection为接口的类型
	ClientReadChan     chan *MsgPack                         //读取消息（客户端的连接等） 这个要传给WsConnection
	Handlers           map[protocol.PackageType]EventHandler //PackageType 这个可以看做事件处理器
	ConnectorHandlers  LogicHandler                          //逻辑处理器的map  路由key->处理方法
	RemoteReadChan     chan []byte                           //读取nats的消息的channel
	RemoteCli          remote.Client                         //nats客户端
}

/*
*
实例化管理器(这方法没有接收器)
*/
func NewManager() *Manager {
	return &Manager{
		ClientReadChan: make(chan *MsgPack, 1024),
		clients:        make(map[string]Connection),
		Handlers:       make(map[protocol.PackageType]EventHandler), //必须初始化，否则报nil map
		RemoteReadChan: make(chan []byte, 1024),                     //实力换读取nats消息的channel
	}
}

/*
*
启动websocket服务入口
*/
func (m *Manager) Run(addr string) {
	go m.clientReadHandler()
	go m.remoteReadHandler()
	http.HandleFunc("/", m.ServeWs)
	m.setupEventHandlers()
	if err := http.ListenAndServe(addr, nil); err != nil {
		zap.S().Errorf("connector listen serve err:%v", err)
	}
}

/*
*
当有客户端连接的时候，会进入这个回调方法
*/
func (m *Manager) ServeWs(w http.ResponseWriter, r *http.Request) {
	//websocket基于http
	if m.websocketUpgrade == nil {
		m.websocketUpgrade = &websocketUpgrade //全局变量赋值到这里
	}
	wsConn, err := m.websocketUpgrade.Upgrade(w, r, nil) //生成一个websocket的连接
	if err != nil {
		zap.S().Errorf("websocketUpgrade.Upgrade err:%v", err)
		return
	}
	client := NewWsConnection(wsConn, m) //将这个连接包装起来--->WsConnection
	m.addClient(client)                  //将当前连接的客户端存储起来
	client.Run()                         //监听读写操作
}

func (m *Manager) addClient(client *WsConnection) {
	m.Lock()
	defer m.Unlock()
	m.clients[client.Cid] = client
}

func (m Manager) removeClient(client *WsConnection) {
	for cid, v := range m.clients {
		if cid == client.Cid {
			v.Close() //先关闭 后删除
			delete(m.clients, cid)
		}
	}
}

func (m *Manager) clientReadHandler() {
	for {
		select {
		case body, ok := <-m.ClientReadChan:
			if ok {
				m.decodeClientPack(body)
			}
		}
	}
}

func (m *Manager) decodeClientPack(body *MsgPack) {
	zap.S().Infof("receive message:%v", string(body.Body))
	packet, err := protocol.Decode(body.Body)
	if err != nil {
		zap.S().Errorf("protocol Decode message err:%v", err)
	}
	err = m.RouteEvent(packet, body.Cid) //	packet.Type //判断他的packageType
	if err != nil {
		zap.S().Errorf("decodeClientPack RouteEvent err:%v", err)
	}
}

/*
*
设置不同的handler
*/
func (m *Manager) setupEventHandlers() {
	m.Handlers[protocol.Handshake] = m.HandshakeHandler
	m.Handlers[protocol.HandshakeAck] = m.HandshakeAckHandler
	m.Handlers[protocol.Heartbeat] = m.HeartbeatHandler
	m.Handlers[protocol.Data] = m.MessageHandler
	m.Handlers[protocol.Kick] = m.KickHandler
}

/*
*
处理握手的handler
*/
func (m *Manager) HandshakeHandler(packet *protocol.Packet, c Connection) error {
	res := protocol.HandshakeResponse{
		Code: 200,
		Sys: protocol.Sys{
			Heartbeat: 3,
		},
	}
	data, _ := json.Marshal(res)
	buf, err := protocol.Encode(packet.Type, data)
	if err != nil {
		zap.S().Errorf("encode packet err:%v", err)
		return err
	}
	return c.SendMessage(buf)
}

// 处理握手确认
func (m *Manager) HandshakeAckHandler(packet *protocol.Packet, c Connection) error {
	zap.S().Info("HandshakeAckHandler")
	return nil
}

/*
*
处理心跳的handler
*/
func (m *Manager) HeartbeatHandler(packet *protocol.Packet, c Connection) error {
	var res []byte
	data, _ := json.Marshal(res)
	buf, err := protocol.Encode(packet.Type, data) //序列化
	if err != nil {
		zap.S().Errorf("encode packet err:%v", err)
	}
	return c.SendMessage(buf)
}

/*
*
普通的消息处理器
*/
func (m *Manager) MessageHandler(packet *protocol.Packet, c Connection) error {
	message := packet.MessageBody()
	zap.S().Infof("receive message body,type:%v,router=%v,data:%v", message.Type, message.Route, string(message.Data))
	//connector.entryHandler.entry  路由
	route := message.Route
	//获取路由的方法
	routeArr := strings.Split(route, ".")
	if len(routeArr) != 3 {
		zap.S().Error("router unsupported")
		return errors.New("router unsupported")
	}
	serverType := routeArr[0]
	connectorServer := gameConfig.Conf.GetConnectorByServerType(serverType)
	handleMethod := fmt.Sprintf("%s.%s", routeArr[1], routeArr[2])
	if connectorServer != nil {
		//说明是本地connector服务处理
		handler, ok := m.ConnectorHandlers[handleMethod]
		if ok {
			handlerData, err := handler(c.GetSession(), message.Data) //执行完获取用户信息后，session设置了uid
			if err != nil {
				return err
			}
			//设置响应信息
			//data转成byte数组
			marshal, err := json.Marshal(handlerData)
			if err != nil {
				return err
			}
			message.Type = protocol.Response
			message.Data = marshal
			encode, err := protocol.MessageEncode(message)
			if err != nil {
				return err
			}
			//再次encode
			res, err := protocol.Encode(packet.Type, encode)
			if err != nil {
				return err
			}
			//发送响应的数据
			c.SendMessage(res)
		}
	} else {
		//nats 远端调用处理 hall.userHandler.updateUserAddress
		dst, err := m.selectDst(serverType)
		if err != nil {
			return err
		}
		session := c.GetSession()
		msg := &remote.Msg{
			Cid:         c.GetSession().Cid,
			Body:        message,
			Src:         m.ServerId,
			Dst:         dst,
			Router:      handleMethod, //指定的方法
			Uid:         c.GetSession().Uid,
			SessionData: session.data,
		}
		data, _ := json.Marshal(msg)
		err = m.RemoteCli.SendMsg(dst, data)
		if err != nil {
			return err
		}
	}
	return nil
}

/*
*
踢人的消息的处理
*/
func (m *Manager) KickHandler(packet *protocol.Packet, c Connection) error {
	zap.S().Info("this is KickHandler")
	return nil
}

/*
*
消息路由
*/
func (m *Manager) RouteEvent(packet *protocol.Packet, cid string) error {
	zap.S().Infof("RouteEvent packet.Type:%v", packet.Type)
	//1 首先获取连接
	connection, ok := m.clients[cid]
	if ok {
		handler, ok := m.Handlers[packet.Type]
		if ok {
			err := handler(packet, connection)
			return err
		} else {
			return errors.New("no packageType found")
		}
	}
	return errors.New("no client found")
}

/*
*
删除连接
*/
func (m *Manager) Close() {
	for cid, connection := range m.clients {
		connection.Close()
		delete(m.clients, cid) //这一块能这样处理吗
	}
}

/*
*
nats选择服务
*/
func (m *Manager) selectDst(serverType string) (string, error) {
	server := gameConfig.Conf.ServersConf.TypeServer
	serverConfig, ok := server[serverType]
	if !ok {
		zap.S().Error("selectDst no server found")
	}
	rand.New(rand.NewSource(time.Now().UnixNano()))
	index := rand.Intn(len(serverConfig))
	serverId := serverConfig[index].ID
	return serverId, nil
}

/*
*
读取connector 在nats订阅的消息

	connector sub nats msg:{"Cid":"3055dfc4-a21c-4fa0-a0be-bba39870c495-connector001-10001","Bo

dy":{"Type":0,"ID":2,"Route":"hall.userHandler.updateUserAddress","Data":"eyJjb2RlIjowLCJtc2ciOm51bGwsInVwZGF0ZVVzZXJEYXRhIjp7ImFkZHJlc3MiOiJ7XCJ4XCI6OTQuN
Dc2LFwieVwiOjQzLjU4MX0iLCJsb2NhdGlvbiI6IiJ9fQ==","Error":false},"Src":"hall-001","Dst":"connector001","Router":"","Uid":"3055dfc4-a21c-4fa0-a0be-bba39870c4
95-connector001-10001","SessionData":null,"Type":0,"PushUser":null}
*/
func (m *Manager) remoteReadHandler() {
	for {
		select {
		case msg := <-m.RemoteReadChan:
			zap.S().Infof("connector(%v) sub nats msg:%v", m.ServerId, string(msg))
		}
	}
}
